package com.jianbo.proxy.core;

import java.util.List;
import java.util.zip.GZIPInputStream;

import org.smartboot.http.server.HttpRequest;

import com.jianbo.proxy.conf.jsconfig.CacheConfig;
import com.jianbo.proxy.entity.HttpResponseMiddle;
import com.jianbo.proxy.util.CommonUtil;
import com.jianbo.proxy.util.ContentTypeUtil;
import com.jianbo.proxy.util.Debug;
import com.jianbo.proxy.util.FileUtil;
import com.jianbo.proxy.util.PathUtil;
import com.jianbo.proxy.util.HttpUtil.HttpResult;
import com.jianbo.proxy.util.RegUtil;

/**
 * 缓存实现
 */
public class CacheWeb implements Web {

    /**
     * 从缓存中读取数据
     */
    @Override
    public boolean handle(String path, HttpRequest request, HttpResponseMiddle response) throws Exception {
        String cachePath = PathUtil.truePath(cacheConfig.getCachePath());
        cachePath = PathUtil.clearEnd(cachePath);
        // to true path
        List<String> matchPaths = cacheConfig.getConfig();
        List<String> excludePaths = cacheConfig.getExclude();
        
        boolean openCache = false;
        for(String mappingReg : excludePaths) {
            boolean match = RegUtil.find(path, mappingReg);
            if(match) {
                return false;
            }
        }

        for(String mappingReg : matchPaths) {
            boolean match = RegUtil.find(path, mappingReg);
            if(match) {
                openCache = true;
            }
        }

        if(openCache) {
            String filePath = cachePath + path;
            // 从文件中读取资源
            
            byte[] bytes = FileUtil.readBytesFast(filePath);
            if(bytes == null) {
                return false;
            }
            setResponse(response, bytes);

            // 根据filePath设置响应头
            String contentType = ContentTypeUtil.contentTypeByPath(path);
            if(contentType != null) {
                response.setHeader("Content-Type", contentType);
            }
            response.setHeader("File-Cache", filePath);

            return true;
        }

        return false;
    }

    // 响应
    private void setResponse(HttpResponseMiddle response, byte[] responseBytes) {
        if(responseBytes != null) {
            response.write(responseBytes);
        }
    }

    // 静态资源缓存
    public void staticCache(String path, HttpResult httpResult) {
        String cachePath = PathUtil.truePath(cacheConfig.getCachePath());
        cachePath = PathUtil.clearEnd(cachePath);
        // to true path
        List<String> matchPaths = cacheConfig.getConfig();
        List<String> excludePaths = cacheConfig.getExclude();
        // Debug.info("excludePaths", excludePaths);
        
        boolean openCache = false;
        for(String mappingReg : excludePaths) {
            boolean match = RegUtil.find(path, mappingReg);
            if(match) {
                // Debug.info("match in exclude", mappingReg + " for " + path);
                return;
            }
        }
        // Debug.info("matchPaths", matchPaths);

        for(String mappingReg : matchPaths) {
            boolean match = RegUtil.find(path, mappingReg);
            if(match) {
                openCache = true;
                break;
            }
        }

        if(openCache) {
            String filePath = cachePath + path;
            // 写入资源到文件中
            String encoding = httpResult.getResponseHeader().get("Content-Encoding");
            Debug.info("save to cache path:" + filePath + " encoding:" + encoding);
            // Debug.info("cache heade", httpResult.getResponseHeader());
            byte[] response = httpResult.getResponse();
            if("gzip".equals(encoding)) {
                response = CommonUtil.unzip(response);
                FileUtil.saveFile(filePath, response);
            } else {
                FileUtil.saveFile(filePath, response);
            }
            // save content type
        }
    }

    private CacheConfig cacheConfig;

    public void setCacheConf(CacheConfig cacheConfig) {
        this.cacheConfig = cacheConfig;
    }
    
}
                                                                                         